package dian.qing.li.demo.security.config.security;

import dian.qing.li.demo.security.constants.Constants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 访问决策管理
 *
 * @author: liqingdian
 **/
public class AppAccessDecisionManager implements AccessDecisionManager {
    @Override
    public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        if (authentication instanceof AnonymousAuthenticationToken || !authentication.isAuthenticated()) {
            throw new BadCredentialsException("未登录");
        }
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        Set<String> authCodes = authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
        boolean auth = configAttributes.stream().anyMatch(a -> StringUtils.equals(Constants.ANONYMOUS_USER, a.getAttribute()) || authCodes.contains(a.getAttribute()));
        if (auth) {
            return;
        }
        //如果没有匹配上，则权限不足
        throw new AccessDeniedException("权限不足");
    }

    @Override
    public boolean supports(ConfigAttribute configAttribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}
